package sword.offer;

/**
 * 请实现一个函数用来判断字符串是否表示数值（包括整数和小数）。
 * 示例 1：
 *
 * 输入：s = "0"
 * 输出：true
 * 示例 2：
 *
 * 输入：s = "e"
 * 输出：false
 * 示例 3：
 *
 * 输入：s = "."
 * 输出：false
 * 示例 4：
 *
 * 输入：s = ".1"
 * 输出：true
 *
 * 链接：https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof
 * @author 胡宇轩
 * @Email: yuxuan.hu01@bianlifeng.com
 */
public class Twenty {
    /**
     * 通过90%+ 的用例，最后十几个特殊用例实在过不了
     * */
    class Solution {
        /**
         * 0: 表示开头, 不能直接结束
         * 1: 表示下一次必须接数字 不能直接结束
         * 2: 表示下次可以接数字 or . or E
         * 3: 表示可以作为 结尾 或者 下次一定要接数字
         * 4： 表示上一个数字是E 可以接负数 或者 数字 不能直接结束
         * 5: 表示上一个是+或者-，必须接.或者数字,并且不能够直接结束
         * */
        int flag;
        boolean isDecimal = false;
        public boolean isNumber(String s) {
            return isNum(s.trim(), 0);
        }

        boolean isNum(String s, int index){
            if(index == s.length()){
                return flag != 1 && flag != 0 && flag != 4 && flag != 5;
            }
            char c = s.charAt(index);
            if(flag == 0){
                if((c == '+' || c == '-')){
                    // flag = 1表示下个字符一定是整数
                    flag = 5;
                }
                else if(c == '.'){
                    if(isDecimal){
                        return false;
                    }
                    isDecimal = true;
                    flag = 1;
                }
                else if(c >= '0' && c <= '9'){
                    flag = 2;
                }else{
                    return false;
                }
                return isNum(s, index+1);
            }

            if(flag == 1 || flag == 3){
                if(c >= '0' && c <= '9'){
                    flag = 2;
                }else{
                    return false;
                }
                return isNum(s, index+1);
            }

            if(flag == 2){
                if(c >= '0' && c <= '9'){
                    return isNum(s, index+1);
                }
                if(c == 'E' || c == 'e'){
                    flag = 4;
                }
                else if(c == '.'){
                    if(isDecimal){
                        return false;
                    }
                    isDecimal = true;
                    flag = 3;
                }
                else{
                    return false;
                }
                return isNum(s, index+1);
            }

            if(flag == 4){
               if(c == '-'){
                   flag = 1;
               }
               else if(c >= '0' && c <= '9'){
                   flag = 3;
               }
               else {
                   return false;
               }
               return isNum(s, index+1);
            }

            if(flag == 5){
                if(c == '.'){
                    flag = 0;
                    return isNum(s, index);
                }else{
                    flag = 3;
                    return isNum(s, index);
                }
            }
           return false;
        }
    }
}
